#pragma once

#pragma pack(1)

typedef struct FLEXFILEHEADER
{
	char	title[0x50];	// (optionnal, filled with 00s)
	long	magic1;			// (seems to be always $FFFF1A00)
	long	count;			// (number of object in table, including empty objects)
	long	magic2;			// (seems to be always $000000CC)
	long	d[9];			// (often set to 0, but sometimes used, meaning?)
} FLEXFILEHEADER, *PFLEXFILEHEADER;

typedef struct FLEXFILEENTRY
{
	long	offset;			// (relative to the beginning of the file)
	long	size;			// note: empty objects are referenced as null offset and null size
} FLEXFILEENTRY, *PFLEXFILEENTRY;

/*
Palette
A palette is an array describing the RGB values for 256 color indexes
This format is compatible with the bios call for setting a palette.
A palette can be found in a flex file or as a separate .PAL file
Format:
  palette = 256 rgb
  rgb     = red green blue
  red     = byte (0..3F)
  green   = byte (0..3F)
  blue    = byte (0..3F)
*/
typedef struct COLORENTRY
{
	char red;			// (0..3F)
	char green;			// (0..3F)
	char blue;			// (0..3F)
} COLORENTRY, *PCOLORENTRY;

#define MAX_COLOR_ENTRIES 256

/*
Tiles
This is a set of graphic tile representing a certain type of floor that
can appears on the ground in the game view. One tile is 8x8 pixel large
Format:
  tiles = set of tile
  tile  = 8x8 pixel
  pixel = byte (index inside the color palette)
*/
const int TILE_WIDTH = 8;
const int TILE_HEIGHT = 8;
const int TILE_LENGTH = TILE_WIDTH * TILE_HEIGHT;
typedef char (*TILE)[TILE_WIDTH];

/*
Shape
This is the graphic representing any item that appears on the game view
except floor tiles. The graphic can include transparent area.
A shape represent a type of object. One shape can have many frames representing
the different appearance of this kind of object. Each frame is describe as a
set of "slices" composing the non-transparent area of the graphic.
A shape can be found in a flex file or as a separate .SHP file
Format:
  shape   = size, set of offset, set of frame
  size    = longint (should be same as in flex table)
  offset  = longint (one for each frame, relative to beginning of shape)
  frame   = rightX, leftX, leftY, rightY, set of slice
    (coordinates are positive distance from the hot spot of the shape)
  slice   = word=0000   (if end of frame)
          | slength, offsetX, offsetY, scontent
    (a slice represents several pixels on the same line)
  slength = word [b0    =type of slice (0=standard, 1=compressed)
                  b1..bF=length in pixel]
  offsetX = integer (relative to hot spot)
  offsetY = integer (relative to hot spot)
  scontent= set of pixel  (if standard slice)
          | set of block  (if compressed slice)
  block   = blength, bcontent
  blength = byte [b0    =type of block (0=standard, 1=repeated pixel)
                  b1..b7=length in pixel]
  bcontent= set of pixel  (if standard block)
          | pixel         (if repeated pixel block)
*/
typedef struct SHAPEENTRY
{
	long	size;			// (should be same as in flex table)
	long	offset[1];		// (one for each frame, relative to beginning of shape)
} SHAPEENTRY, *PSHAPEENTRY;

typedef struct FRAMEENTRY
{
	short	rightX;			// (coordinates are positive distance from the hot spot of the shape)
	short	leftX;
	short	topY;
	short	bottomY;
	char	slice[1];
} FRAMEENTRY, *PFRAMEENTRY;

typedef struct SLICEENTRY
{
	unsigned short type:1;		// (0=standard, 1=compressed)
	unsigned short length:15;	// length in pixel
	short	offsetX;			// (relative to hot spot)
	short	offsetY;			// (relative to hot spot)
	char	content[1];			// set of pixel  (if standard slice) | set of block  (if compressed slice)
} SLICEENTRY, *PSLICEENTRY;

typedef struct SLICECONTENT
{
	unsigned char type:1;		// type of block (0=standard, 1=repeated pixel)
	unsigned char length:7;		// length in pixel
	char	pixel[1];			// set of pixel  (if standard block) | pixel (if repeated pixel block)
} SLICECONTENT, *PSLICECONTENT;

/*
U7CHUNKS:     $C00 chunks
  chunk   = 16x16 shapeID
  shapeID = word [b0..b9=shapeType  (0..$400-1)
                  bA..bE=shapeFrame (0..$20-1)
                  bF=? ]
*/
typedef struct SHAPEID
{
	unsigned short shapeType:10;
	unsigned short shapeFrame:5;
	unsigned short reserved:1;
} SHAPEID, *PSHAPEID;

typedef const SHAPEID* CONST_PSHAPEID;

const int CHUNK_WIDTH = 16;
const int CHUNK_HEIGHT = 16;
const int CHUNK_LENGTH = CHUNK_WIDTH * CHUNK_HEIGHT;

typedef SHAPEID CHUNK[CHUNK_LENGTH];

const int SUPERCHUNK_WIDTH = 16;
const int SUPERCHUNK_HEIGHT = 16;
const int SUPERCHUNK_LENGTH = SUPERCHUNK_WIDTH * SUPERCHUNK_HEIGHT;

typedef unsigned short CHUNKID; // 0..0xc00-1
typedef CHUNKID SUPERCHUNK[SUPERCHUNK_LENGTH];

const int MAP_WIDTH = 12;
const int MAP_HEIGHT = 12;
const int MAP_LENGTH = MAP_WIDTH * MAP_HEIGHT;

typedef SUPERCHUNK MAP[MAP_LENGTH];

const int MAP_WIDTH_IN_SUPERCHUNKS = MAP_WIDTH; // 12
const int MAP_WIDTH_IN_CHUNKS  = MAP_WIDTH_IN_SUPERCHUNKS * SUPERCHUNK_WIDTH; // 12 * 16 = 192
const int MAP_WIDTH_IN_TILES   = MAP_WIDTH_IN_CHUNKS * CHUNK_WIDTH; // 12 * 16 * 16
const int MAP_WIDTH_IN_PIXELS  = MAP_WIDTH_IN_TILES * TILE_WIDTH; // 12 * 16 * 16 * 8 = 24576

const int MAP_HEIGHT_IN_SUPERCHUNKS = MAP_HEIGHT; // 12
const int MAP_HEIGHT_IN_CHUNKS  = MAP_HEIGHT_IN_SUPERCHUNKS * SUPERCHUNK_HEIGHT; // 12 * 16
const int MAP_HEIGHT_IN_TILES   = MAP_HEIGHT_IN_CHUNKS * CHUNK_HEIGHT; // 12 * 16 * 16
const int MAP_HEIGHT_IN_PIXELS  = MAP_HEIGHT_IN_TILES * TILE_HEIGHT; // 12 * 16 * 16 * 8 = 24576

/*
SHPDIMS.DAT:  $400-$96 shpdims  (one for each Game Shape)
  shpdims = dimY, dimX
  dimY    = byte [b0: obstacle in N-S direction?
                  b1..b7: Y dimension of the shape=number of tiles covered?]
  dimX    = byte [b0: obstacle in W-E direction?
                  b1..b7: X dimension of the shape=number of tiles covered?]
*/
typedef struct SHPDIMS
{
	unsigned char obstacleNS:1;
	unsigned char yTiles:7;
	unsigned char obstacleWE:1;
	unsigned char xTiles:7;
} SHPDIMS, *PSHIPDIMS;

/*
WGTVOL.DAT:   $400 wgtvol       (one for each Game Shape & Tiles)
  wgtvol  = weight, volume
  weight  = byte: weight of the shape (in 0.1 stone)
  volume  = byte: volume of the shape
    (stone is the unit used in the inventory window in the game)
*/
typedef struct WGTVOL
{
	unsigned char weight;
	unsigned char volume;
} WGTVOL, *PWGTVOL;

/*
TFA.DAT:      $400 entries (one for each Game Shape & Tiles)
  tfa     = $400 triplet
  triplet = tfa1, tfa2, tfa3
  tfa1    = byte [b0..1 =?
                  b2    =animated shape
                  b3..4 =?
                  b5..b7=height of shape]
  tfa2    = byte [b0..b6=?

                  b7    =is transparent (cannot be selected, cannot place item on it)]
  tfa3    = byte [b0..b2=X size of the shape - 1  (number of tiles covered)
                  b3..b5=Y size of the shape - 1  (number of tiles covered)
                  b6    =is a light source
                  b7    =contains transparency colors (light,dark,blood)]
*/

enum SHAPE_CLASS
{
	unusable		= 0,	// Trees.
	quality			= 2,
	quantity		= 3,	// Can have more than 1:  coins, arrs.
	has_hp			= 4,    // Breakable items (if hp != 0, that is)
	quality_flags	= 5,	// Item quality is set of flags:
	                        // Bit 3 = okay-to-take.
	container		= 6,
	hatchable		= 7,	// Eggs, traps, moongates.
	spellbook		= 8,
	barge			= 9,
	virtue_stone	= 11,
	monster			= 12,	// Non-human's.
	human			= 13,	// Human NPC's.
	building		= 14	// Roof, window, mountain.
};

typedef struct TFA
{
	// tfa1
	unsigned char unknown1:2;
	unsigned char animated:1;
	unsigned char unknown2:2;
	unsigned char zTiles:3;
	// tfa2
	unsigned char shapeClass:4;
	unsigned char unknown3:3;
	unsigned char isTransparent:1;
	// tfa3
	unsigned char xTiles:3; // x size of the shape - 1
	unsigned char yTiles:3; // y size of the shape - 1
	unsigned char isLight:1;
	unsigned char containsTransparencyColors:1;
} TFA, *PTFA;

#pragma pack()
